﻿using UnityEngine;
using UnityEditorInternal;
using System.Collections;
using UnityEditor;
using NodeCanvas;
using System.Collections.Generic;
public class PanelMakerEditor : NodeEditor {
	
	#region Member
	protected override float _rightPanelWidth {
		get {
			return base._rightPanelWidth*3;
		}
	}
	protected override string _currentCanvasName {
		get {
			return "";
		}
	}
	protected override float _miniNodeAreHight {
		get {
			return 0;
		}
	}
	protected override bool _canDragNode {
		get {
			return false;
		}
	}
	protected override bool CanDraw {
		get {
			return compilingMode == CompilingMode.None;
		}
	}
	Vector2 clipDataPos;
	CompilingMode compilingMode = CompilingMode.None;
	PanelMakerScriptableObject _scriptableObject;
	ReorderableList _pmClipDataList;
	public PMViewData viewData = new PMViewData();
	public GameObject ViewObject;
	Vector2 viewDatapos = new Vector2();
	#endregion
	[MenuItem("Assets/Node/PM/Open Editor")]
	public static void Init(){
		var window =  GetWindow<PanelMakerEditor> ();
		Debug.Log ("init");
		window.FindAssetsSeekersScriptableObject ();
	}

	void Update() {
		if (compilingMode != CompilingMode.None) {
			if (!EditorApplication.isCompiling) {
				switch (compilingMode) {
				case CompilingMode.Module:
					compilingMode = CompilingMode.None;
					OnCompingFinish_Module ();
					break;
				case CompilingMode.View:
					compilingMode = CompilingMode.None;
					OnCompingFinish_View ();
					break;
				}
			}
		} else {
			
		}
	}
	void OnHierarchyChange(){
		if(_startNode != null)
			LoadViewData (_startNode.name);
	}
	#region Data

	void UpdateNodes(){
		_nodes.Clear ();
		for (int i = 0; i < _scriptableObject.ShowNodes.Count; i++) {
			_nodes .Add( _scriptableObject.ShowNodes[i]);
			_scriptableObject.ShowNodes[i].position.position = new Vector2 (0, i * 50);

		}
		allNodes = _scriptableObject.nodes;
	}
	void UpdateReorderable(){
		_pmClipDataList = new ReorderableList(_scriptableObject.NodeClips,typeof(PMClipData),true,true,true,true);
		_pmClipDataList.drawElementCallback = OnDrawReorderabel;
		_pmClipDataList.onAddCallback = OnAddClipData;
		_pmClipDataList.onRemoveCallback = OnRemoveClipData;
		_pmClipDataList.onSelectCallback = delegate(ReorderableList list) {
			_scriptableObject.currentClipid = list.index;
			UpdateNodes();
		};
	}

	void OnRemoveClipData(ReorderableList list){
		if (EditorUtility.DisplayDialog("警告", "是否真的要删除这个场景？", "是", "否"))
		{
			string name = _scriptableObject.NodeClips [list.index].ClipName;
			PMTool.DeleModule (name);
			ReorderableList.defaultBehaviours.DoRemoveButton(list);
		}
	}

	void OnAddClipData(ReorderableList list){
		MyDisplay.InputTextsss (this,"创建一个场景", "确定", "取消", delegate(string obj) {
			obj = obj.Substring (0, 1).ToUpper () + obj.Substring (1);
			if(obj == "")
				return;
			for(int i =0;i < _scriptableObject.NodeClips.Count;i++){
				if(_scriptableObject.NodeClips[i].ClipName == obj)
					return;
			}
			ReorderableList.defaultBehaviours.DoAddButton(list);
			PMClipData clipdata = (PMClipData)list.list[list.list.Count - 1];
			clipdata.ClipName = obj;
			_scriptableObject.currentClipid = _scriptableObject.NodeClips.Count-1;
			PMTool.CreateModule(obj);
			compilingMode = CompilingMode.Module;
		});
	}
		
	void CreatePanel(string name){
		string modulename = _scriptableObject.CurrentClip.ClipName;
		PMTool.CreateScriptModulePanel (PMConst.PathModule + modulename + "/Panel/",name);
		PMTool.UpdateBaseView(PMConst.PathModule+modulename+"/Panel/",name+"_View");
		PMTool.RefreshAssets ();
		compilingMode = CompilingMode.View;
	}
	#endregion

	#region Action
	void FindAssetsSeekersScriptableObject(){
		_scriptableObject = AssetDatabase.LoadAssetAtPath<PanelMakerScriptableObject>(PanelMakerScriptableObject.ASAssetsPath+".asset");
		if (_scriptableObject == null)
			_scriptableObject = PanelMakerScriptableObject.Execute ();
		FindModule ();
		UpdateNodes ();
		UpdateReorderable ();
		_currentGroupPath = _scriptableObject.currentGroupPath;
		Repaint ();
	}

	void FindModule(){
		string[] moduleds = PMTool.GetDirectories (PMConst.PathModule);
		List<string> listModuleds = new List<string>(moduleds);
		List<string> listNodeClipName = new List<string> ();
		for (int i = 0; i < listModuleds.Count; i++) {
			listModuleds [i] = System.IO.Path.GetFileNameWithoutExtension (listModuleds [i]);
		}
		for (int i = 0; i < _scriptableObject.NodeClips.Count; i++) {
			listNodeClipName.Add (_scriptableObject.NodeClips [i].ClipName);
		}
		for (int i = 0;  i < moduleds.Length; i++) {
			string cname =  System.IO.Path.GetFileNameWithoutExtension (listModuleds [i]);
			if (!listNodeClipName.Contains (cname)) {
				_scriptableObject.AddNodeClip ();	
				PMClipData data = _scriptableObject.NodeClips [_scriptableObject.NodeClips.Count - 1];
				data.ClipName = cname;
				FindPanel (moduleds [i], data);
			}
	
		}
		for (int i = 0; i < _scriptableObject.NodeClips.Count; i++) {
			string cname = _scriptableObject.NodeClips [i].ClipName;
			if(!listModuleds.Contains(cname)){
				_scriptableObject.NodeClips.Remove (_scriptableObject.NodeClips [i]);
				i--;
			}
		}

	}


	void FindPanel(string path,PMClipData data){
		string[] moduleds = PMTool.GetFiles (path+"/Panel/");
		int count = 0;
		for (int i = 0; i < moduleds.Length; i++) {
			string name = System.IO.Path.GetFileNameWithoutExtension (moduleds [i]);
			string[] sp = name.Split ('_');
			if (System.IO.Path.GetExtension (moduleds [i]) != ".meta" && sp[sp.Length-1] == "View") {
				count++;
				bool has = false;
				

				for (int x = 0; x < data.nodes.Length; x++) {
					if (data.nodes [x].name == name) {
						has = true;
						break;
					}
				}
				if (!has && !name.Contains ("Base")) {
					if (i>=data.nodes.Length) {
						PMNode _node = data.AddNode (new Vector2 (0, i * 20));
						_node.name = name;
					} else {
						data.nodes [i].name = name;
					}
				}
			}
		}
		while (count < data.nodes.Length) {
			data.RemoveNode (data.nodes [data.nodes.Length - 1]);
		}
	}

	void SetDefault(Node _node){
		_startNode = _node;
		_scriptableObject.SetDefaultState(_node);
	}

	void OnCompingFinish_Module(){
		string clipname = _scriptableObject.CurrentClip.ClipName;
		PMTool.GetObjWithComponent (PMConst.PathModule +clipname+"/MVC/", clipname+"Control");
	}

	void OnCompingFinish_View(){
		string clipname = _scriptableObject.CurrentClip.ClipName;
		string viewname = _scriptableObject.CurrentClip.nodes[_scriptableObject.CurrentClip.nodes.Length-1].name;
		PMTool.OnComingFinish (clipname,viewname);
		string nodepath = "Base/" + viewname;
		Node _node = FindNodeWithPath (nodepath);
		_selectNodes.Clear ();
		_selectNodes.Add (_node);
		SetDefault (_node);
		ViewObject = GameObject.Find (viewname);
	}


	void LoadViewData(string viewname){
		GameObject obj = GameObject.Find (viewname);
		if (obj == null)
			return;
		viewData.LoadData (obj);
	}

	#endregion

	#region Panel
	protected override void DrawRightPanel ()
	{
		DrawAddComponents();
		if (viewData != null) {
			viewDatapos = EditorGUILayout.BeginScrollView (viewDatapos);
			viewData.ShowGUI ();
			EditorGUILayout.EndScrollView ();
		}
		EditorGUILayout.Space ();
		EditorGUILayout.LabelField ("----");
	}
	void DrawAddComponents(){
		EditorGUILayout.BeginHorizontal ("box");
		DrawAddComponent<UISprite>();
		DrawAddComponent<UILabel>();
		DrawAddComponent<UIToggle>();
		DrawAddComponent<BoxCollider>("Button","btn_Click");
		EditorGUILayout.EndHorizontal ();
	}
	void DrawAddComponent<T>(string name = "",string gameObjectname = "")where T:Component{
		string typename =name == ""? typeof(T).Name:name;
		if (GUILayout.Button (typename)) {
			GameObject child = new GameObject (gameObjectname == ""?typename:gameObjectname);
			GameObject parent = Selection.activeGameObject;
			if (parent.GetComponentInParent<ViewUI> () == null)
				parent = ViewObject;
			child.transform.parent = parent.transform;
			child.transform.localScale = Vector3.one;
			try{
				child.gameObject.layer = LayerMask.NameToLayer("UI");
			}
			catch{
				
			}
			child.gameObject.AddComponent<T> ();
			Selection.activeGameObject = child;
		}
	}
	void OnDrawReorderabel(Rect r,int id,bool isactive,bool isfocused){
		PMClipData clip = (PMClipData)_scriptableObject.NodeClips[id];
		GUI.Label(r,clip.ClipName);
	}

	protected override void DrawLeftPanel ()
	{
		clipDataPos = EditorGUILayout.BeginScrollView (clipDataPos);
		if (_pmClipDataList == null)
			FindAssetsSeekersScriptableObject ();
		_pmClipDataList.DoLayoutList();
		EditorGUILayout.EndScrollView ();
	}

	protected override void ContextMenu_Canvas (ref GenericMenu menu)
	{
		menu.AddItem (new GUIContent ("添加界面"), false, delegate {
			MyDisplay.InputTextsss(this,"创建一个界面","OK","Cancel",delegate(string obj) {
				if(obj.Contains("Base"))
					return;
				obj = obj.Substring (0, 1).ToUpper () + obj.Substring (1);
				Node _node = AddNode(_scriptableObject.AddNode (_cachedMousePosition-_canvasOffset));
				_node.SetName(obj+"_View");

				UpdateNodes();
				_selectNodes = new List<Node>();
				_selectNodes.Add(_node);
				CreatePanel(obj);
			});
		});
	}

	protected override void ContextMenu_Node (ref GenericMenu menu)
	{
		

		if (_startNode == null || (_selectNode.GetPath() != _startNode.GetPath())) {
			menu.AddItem (new GUIContent ("加载"), false, delegate() {
				string clipname = _scriptableObject.CurrentClip.ClipName;
				clipname = clipname.Replace("Module","");
				ViewObject = PMTool.LoadView ("ViewUI/" + clipname + "/", _selectNode.name);
				SetDefault (_selectNode);
				LoadViewData(_selectNode.name);
			});


		} else {
			menu.AddItem (new GUIContent ("保存"), false, delegate() {
				string clipname = _scriptableObject.CurrentClip.ClipName;
				clipname = clipname.Replace("Module","");
				PMTool.SaveView (Application.dataPath + "/Resources/ViewUI/" + clipname + "/", _selectNode.name);
				SetDefault(null);
			});

			menu.AddItem (new GUIContent ("自动化刷新Base"), false, delegate {
				string modulename = _scriptableObject.CurrentClip.ClipName;
				PMTool.UpdateBaseView(PMConst.PathModule+modulename+"/Panel/",_selectNode.name);
				PMTool.RefreshAssets();
			});
		}
		menu.AddItem (new GUIContent ("打开View"), false, delegate() {
			string modulename = _scriptableObject.CurrentClip.ClipName;
			PMTool.OpenView(PMConst.PathModule+modulename+"/Panel/"+_selectNode.name);
		});

		menu.AddItem (new GUIContent ("打开ViewModel"), false, delegate() {
			string modulename = _scriptableObject.CurrentClip.ClipName;
			PMTool.OpenView(PMConst.PathModule+modulename+"/Panel/"+_selectNode.name.Split('_')[0]+"_ViewModel");
		});	

		menu.AddItem (new GUIContent ("打开Model"), false, delegate() {
			string modulename = _scriptableObject.CurrentClip.ClipName;
			PMTool.OpenView(PMConst.PathModule+modulename+"/Panel/"+_selectNode.name.Split('_')[0]+"_Model");
		});
	}

	protected override void DrawMainTool ()
	{
		if (GUILayout.Button ("模板",NodeStyles.breadcrumbLeft)) {
			string[] tems = PMTool.GetFiles (PMConst.PMTemplate);
			GenericMenu menu = new GenericMenu ();
			for(int i =0;i<tems.Length;i++){
				string ex = System.IO.Path.GetExtension (tems [i]);
				string filename = System.IO.Path.GetFileNameWithoutExtension (tems [i]);
				if (ex != ".meta") {
					menu.AddItem (new GUIContent (filename), false, delegate(object obj) {
						PMTool.OpenFile<TextAsset>(PMConst.PMTemplate+"/"+filename+".txt");
					}, filename);
				}
			}
			menu.ShowAsContext ();
		}

		if (GUILayout.Button ("场景", NodeStyles.breadcrumbMiddle)) {
			string[] module = PMTool.GetDirectories (PMConst.PathModule);
			GenericMenu menu = new GenericMenu ();
			for(int i =0;i<module.Length;i++){
				string ex = System.IO.Path.GetExtension (module [i]);
				string filename = System.IO.Path.GetFileNameWithoutExtension (module [i]);
				if (ex != ".meta") {
					menu.AddItem (new GUIContent (filename), false, delegate(object obj) {
						filename = filename.Replace("Module","");
						string ctrlpath = PMConst.PathModule+filename+"/MVC/"+filename+"Control.cs";
						Debug.Log(ctrlpath);
						PMTool.OpenFile<TextAsset>(ctrlpath);
					}, filename);
				}
			}
			menu.ShowAsContext ();
		}
	}
	#endregion
}

public class PMViewData{
	public PMViewComponent<UISprite> uisprites = new PMViewComponent<UISprite>();
	public PMViewComponent<UILabel> uilabels = new PMViewComponent<UILabel>();
	public PMViewComponent<UISlider> uisliders = new PMViewComponent<UISlider> ();
	public PMViewComponent<UIToggle> uitoggle = new PMViewComponent<UIToggle> ();
	public PMViewComponent<BoxCollider> uiboxcollider = new PMViewComponent<BoxCollider> ();

	public void LoadData(GameObject obj){
		uisprites.LoadData (obj);
		uilabels.LoadData (obj);
		uisliders.LoadData (obj);
		uitoggle.LoadData (obj);
		uiboxcollider.LoadData (obj);
	}
	public void ShowGUI(){
//		pos = EditorGUILayout.BeginScrollView (pos);
		uisprites.ShowGUI ();
		uilabels.ShowGUI ();
		uisliders.ShowGUI ();
		uitoggle.ShowGUI ();
		uiboxcollider.ShowGUI ();
//		EditorGUILayout.EndScrollView ();
	}
}

public class PMViewComponent<T> where T:Component{
	public T[] t;
	public void LoadData(GameObject obj){
		t = obj.GetComponentsInChildren<T> ();
	}

	public void ShowGUI(){
		if (t == null)
			return;
		
		for (int i = 0; i < t.Length; i++) {
			if (t [i] != null) {
				bool error = getObjsNumByName (t [i].gameObject.name) > 1;
				if (error) {
					EditorGUILayout.HelpBox ("警告!不允许相同控件重名",MessageType.Warning);
					GUI.backgroundColor = Color.red;
				} else if (t [i].gameObject.name.Contains (tag)) {
					GUI.backgroundColor = Color.green;
				} else {
					GUI.backgroundColor = Color.white;
				}

				EditorGUILayout.BeginHorizontal ("box");

				string name = t [i].gameObject.name;
				bool use = name.Length > 3 && name.Contains (tag);
				bool newuse;
				newuse = EditorGUILayout.Toggle (use) && !error;

				if (newuse != use) {
					if (newuse)
						name = tag + name;
					else
						name = name.Replace (tag, "");
				}

//				string _tag = newuse == true ? tag : "";
				EditorGUILayout.LabelField (tag);
				string[] sp = name.Split ('_');
				string oldsp = "";
				for(int x =0;x < sp.Length-1;x++){
					oldsp+= sp[x]+((x==sp.Length-1)?"":"_");
				}
				name = EditorGUILayout.TextField (sp[sp.Length-1]);

				name = name.Substring (0, 1).ToUpper () + name.Substring (1);
				name = oldsp + name;
				if(GUI.changed)
					t [i].gameObject.name = name;

				EditorGUILayout.ObjectField (t [i].gameObject, typeof(GameObject),true);
				EditorGUILayout.EndHorizontal ();
			}
		}
	}
	int getObjsNumByName(string name){
		int num = 0;
		for (int i = 0; i < t.Length; i++) {
			if (t [i].name == name)
				num++;
		}
		return num;
	}


	string _tag = "";
	string tag{
		get{ 
			if (_tag == "") {
				_tag = PMTool.GetUIComponentTag<T> ();
			}
			return _tag;
		}
	}
}
